package org.example.study11.deadlyembrace;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class TimeoutSolution {
    // 使用ReentrantLock，支持带超时的tryLock方法
    private static final Lock lock1 = new ReentrantLock();
    private static final Lock lock2 = new ReentrantLock();

    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            // 线程1：尝试按lock1->lock2顺序获取，但支持超时
            processWithTimeout("线程1", lock1, lock2);
        });

        Thread t2 = new Thread(() -> {
            // 线程2：尝试按lock2->lock1顺序获取，同样支持超时
            processWithTimeout("线程2", lock2, lock1);
        });

        t1.start();
        t2.start();
    }


    /**
     * 使用带超时的锁获取机制
     * 核心思想：为锁获取操作设置时间限制，避免无限期等待
     * @param threadName 线程名称
     * @param firstLock 第一个要获取的锁
     * @param secondLock 第二个要获取的锁
     */
    private static void processWithTimeout(String threadName, Lock firstLock, Lock secondLock) {
        try {
            // 尝试在指定时间内获取第一个锁
            // tryLock(1, TimeUnit.SECONDS)会等待最多1秒，如果获取不到返回false
            if (firstLock.tryLock(1, TimeUnit.SECONDS)) {
                try {
                    System.out.println(threadName + ": 成功获取第一个锁");

                    // 模拟业务处理
                    TimeUnit.MILLISECONDS.sleep(100);

                    // 尝试在指定时间内获取第二个锁
                    if (secondLock.tryLock(1, TimeUnit.SECONDS)) {
                        try {
                            System.out.println(threadName + ": 成功获取第二个锁，执行关键业务");
                            performCriticalSection(threadName);
                        } finally {
                            // 释放第二个锁 - 必须放在finally中
                            secondLock.unlock();
                        }
                    } else {
                        // 获取第二个锁超时处理
                        System.out.println(threadName + ": 获取第二个锁超时");
                    }
                } finally {
                    // 释放第一个锁 - 必须放在finally中，确保锁被释放
                    firstLock.unlock();
                }
            } else {
                // 获取第一个锁超时处理
                System.out.println(threadName + ": 获取第一个锁超时");
            }
        } catch (InterruptedException e) {
            System.out.println(threadName + ": 被中断");
            Thread.currentThread().interrupt();
        }
    }

    private static void performCriticalSection(String threadName) {
        System.out.println(threadName + ": 正在执行关键业务代码");
        try {
            TimeUnit.MILLISECONDS.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(threadName + ": 关键业务执行完成");
    }
}